package com.pic.mgt.telnetd;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.Socket;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;

import net.wimpi.telnetd.BootException;
import net.wimpi.telnetd.io.terminal.TerminalManager;
import net.wimpi.telnetd.net.PortListener;
import net.wimpi.telnetd.shell.ShellManager;
import net.wimpi.telnetd.util.PropertiesLoader;
import net.wimpi.telnetd.util.StringUtil;

import com.pic.mgt.log.IgxLog;


public class TelnetD {
	
	public static String defaultCommandPrefixHintStr;
	public static String consoleTitleStr;
	
	private static TelnetD telnetD = null;
	
	private ShellManager shellManager;
	private List<PortListener> portListenerList;
	
	private TelnetD(String propertieFile) throws TelnetdException {
		this.portListenerList = new LinkedList<PortListener>();
		
		
		// 讀取 telnetd 的設定檔出來
		Properties properties = null;
		try {
			properties = PropertiesLoader.loadProperties(propertieFile);
		} catch (MalformedURLException e) {
			// ********************** Log **********************
			IgxLog.messageDetailsLog.error(this, e.getMessage());
			// ********************** Log **********************
			
			throw new TelnetdException(
					"Loading telnetd property file '" + propertieFile + "' failed.", e);
		} catch (IOException e) {
			// ********************** Log **********************
			IgxLog.messageDetailsLog.error(this, e.getMessage());
			// ********************** Log **********************
			
			throw new TelnetdException(
					"Loading telnetd property file '" + propertieFile + "' failed.", e);
		}
		
		
		// 建立 ShellManager
		try {
			this.shellManager = ShellManager.createShellManager(properties);
		} catch (BootException e) {
			// ********************** Log **********************
			IgxLog.messageDetailsLog.error(this, e.getMessage());
			// ********************** Log **********************
			
			throw new TelnetdException(
					"Loading telnetd services failed in creating shell manager step.", e);
		}
		
		
		// 建立 TerminalManager
		try {
			TerminalManager.createTerminalManager(properties);
		} catch (BootException e) {
			// ********************** Log **********************
			IgxLog.messageDetailsLog.error(this, e.getMessage());
			// ********************** Log **********************
			
			throw new TelnetdException(
					"Loading telnetd services failed in creating terminal manager step.", e);
		}
		
		
		// 建立 PortListener
		String[] listnerNamesArray = StringUtil.split(properties.getProperty("listeners"), ",");
		try {
			for (String listenerName : listnerNamesArray) {
				this.portListenerList.add(
						PortListener.createPortListener(listenerName, properties));
			}
		} catch (BootException e) {
			// ********************** Log **********************
			IgxLog.messageDetailsLog.error(this, e.getMessage());
			// ********************** Log **********************
			
			throw new TelnetdException(
					"Loading telnetd services failed in creating port listener step.", e);
		}
		
		// 建立完成
	}
	
	/**
	 * 開始 Telnet 服務。
	 */
	public synchronized void startTelnetD() {
		for (PortListener portListener : this.portListenerList) {
			/*
			 * 如果 port 被佔用,會輸出error log,但無法 catch到 exception
			 */
			portListener.start();
		}
	}
	
	/**
	 * 停止 TelnetD 服務
	 */
	public synchronized void stopTelnetD() {
		for (PortListener portListener : this.portListenerList) {
			// 直接將所有 Console 連線關閉
			int currentConsoleCount = portListener.getConnectionManager().openConnectionCount();
			for (int i=0;i<currentConsoleCount;i++) {
				Socket socket = portListener.getConnectionManager().getConnection(i).getConnectionData().getSocket();
				if (null != socket) {
					try {
						socket.close();
					}
					catch (IOException e) {}
					catch (Exception e) {}
				}
			}
			
			portListener.stop();
		}
	}
	
	public synchronized static TelnetD getInstance(String propertieFile) throws TelnetdException {
		if (null == telnetD) {
			telnetD = new TelnetD("file:" + propertieFile);
		}
		
		return telnetD;
	}
	
	// --- getter and setter ---

	public void setDefaultCommandPrefixHintStr(
			String defaultCommandPrefixHintStr) {
		TelnetD.defaultCommandPrefixHintStr = defaultCommandPrefixHintStr;
	}

	public void setConsoleTitleStr(String consoleTitleStr) {
		TelnetD.consoleTitleStr = consoleTitleStr;
	}
}
